pub mod lexer;

#[derive(Debug, Clone, PartialEq)]
pub enum Token {
    Identifier(String),
    Literal(Literal),
    Keyword(Keyword),
    Symbol(Symbol),
    Newline,
    Whitespace,
    Comment(String),
    EOF,
}

#[derive(Debug, Clone, PartialEq)]
pub struct Position {
    pub line: usize,
    pub column: usize,
}
#[derive(Debug, Clone, PartialEq)]
pub struct SpannedToken {
    pub token: Token,
    pub position: Position,
}
#[derive(Debug, Clone, PartialEq)]
pub enum Symbol {
    LeftParen,    // (
    RightParen,   // )
    LeftBrace,    // {
    RightBrace,   // }
    LeftBracket,  // [
    RightBracket, // ]
    Semicolon,    // ;
    Colon,        // :
    Comma,        // ,
    Dot,          // .
    Plus,         // +
    Minus,        // -
    Star,         // *
    Slash,        // /
    Percent,      // %
    Equal,        // =
    Less,         // <
    Greater,      // >
    Bang,         // !
    Question,     // ?
    Amp,          // &
    Pipe,         // |
    Caret,        // ^
    Tilde,        // ~
    At,           // @
    Hash,         // #
    Dollar,       // $
    Backtick,     // `
    DoubleQuote,  // "
    SingleQuote,  // '
    DoubleEqual,  // ==
    NotEqual,     // !=
    LessEqual,    // <=
    GreaterEqual, // >=
    LeftArrow,    // <-
    RightArrow,   // ->
    FatArrow,     // =>
    DoublePlus,   // ++
    DoubleMinus,  // --
    PlusEqual,    // +=
    MinusEqual,   // -=
    StarEqual,    // *=
    SlashEqual,   // /=
    PercentEqual, // %=
    AmpEqual,     // &=
    PipeEqual,    // |=
    CaretEqual,   // ^=
    DoubleAmp,    // &&
    DoublePipe,   // ||
    LeftShift,    // <<
    RightShift,   // >>
    Ellipsis,     // ...
    ColonColon,   // ::
}

#[derive(Debug, Clone, PartialEq)]
pub enum Keyword {
    Return, // return 
    Break, // break 
    Continue, // continue 
    If, // if 
    Else, // else 
    Elif, // elif 
    For, // for 
    While, // while 
    Loop, // loop 
    Match, // match 
    Fn, // fn 
    Struct, // struct 
    Enum, // enum 
    Const, // const 
    Static, // static 
    Type, // type 
    As, // as 
    In, // in 
    Where, // where 
    Async, // async 
    Await, // await 
    True, // true 
    False, // false 
    Null, // null 
    New, // new 
    Yield, // yield 
    Import, // import
    Export, // export
    From, // from
}

#[derive(Debug, Clone, PartialEq)]
pub enum Literal {
    Integer(i64),
    Float(f64),
    Char(char),
    String(String),
    ByteString(Vec<u8>),
    Boolean(bool),
}


impl std::fmt::Display for Token {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match self {
            Token::Identifier(name) => write!(f, "标识符: {}", name),
            Token::Symbol(sym) => write!(f, "{}", sym),
            Token::Keyword(kw) => write!(f, "{}", kw),
            Token::Literal(lit) => write!(f, "{}", lit),
            Token::Newline => write!(f, "换行符"),
            Token::Whitespace => write!(f, "空白符"),
            Token::Comment(text) => write!(f, "注释: {}", text),
            Token::EOF => write!(f, "文件结束符"),
        }
    }
}

impl std::fmt::Display for Symbol {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match self {
            Symbol::LeftParen => write!(f, "("),
            Symbol::RightParen => write!(f, ")"),
            Symbol::LeftBrace => write!(f, "{{"),
            Symbol::RightBrace => write!(f, "}}"),
            Symbol::LeftBracket => write!(f, "["),
            Symbol::RightBracket => write!(f, "]"),
            Symbol::Semicolon => write!(f, ";"),
            Symbol::Colon => write!(f, ":"),
            Symbol::Comma => write!(f, ","),
            Symbol::Dot => write!(f, "."),
            Symbol::Plus => write!(f, "+"),
            Symbol::Minus => write!(f, "-"),
            Symbol::Star => write!(f, "*"),
            Symbol::Slash => write!(f, "/"),
            Symbol::Percent => write!(f, "%"),
            Symbol::Equal => write!(f, "="),
            Symbol::Less => write!(f, "<"),
            Symbol::Greater => write!(f, ">"),
            Symbol::Bang => write!(f, "!"),
            Symbol::Question => write!(f, "?"),
            Symbol::Amp => write!(f, "&"),
            Symbol::Pipe => write!(f, "|"),
            Symbol::Caret => write!(f, "^"),
            Symbol::Tilde => write!(f, "~"),
            Symbol::At => write!(f, "@"),
            Symbol::Hash => write!(f, "#"),
            Symbol::Dollar => write!(f, "$"),
            Symbol::Backtick => write!(f, "`"),
            Symbol::DoubleQuote => write!(f, "\""),
            Symbol::SingleQuote => write!(f, "'"),
            Symbol::DoubleEqual => write!(f, "=="),
            Symbol::NotEqual => write!(f, "!="),
            Symbol::LessEqual => write!(f, "<="),
            Symbol::GreaterEqual => write!(f, ">="),
            Symbol::LeftArrow => write!(f, "<-"),
            Symbol::RightArrow => write!(f, "->"),
            Symbol::FatArrow => write!(f, "=>"),
            Symbol::DoublePlus => write!(f, "++"),
            Symbol::DoubleMinus => write!(f, "--"),
            Symbol::PlusEqual => write!(f, "+="),
            Symbol::MinusEqual => write!(f, "-="),
            Symbol::StarEqual => write!(f, "*="),
            Symbol::SlashEqual => write!(f, "/="),
            Symbol::PercentEqual => write!(f, "%="),
            Symbol::AmpEqual => write!(f, "&="),
            Symbol::PipeEqual => write!(f, "|="),
            Symbol::CaretEqual => write!(f, "^="),
            Symbol::DoubleAmp => write!(f, "&&"),
            Symbol::DoublePipe => write!(f, "||"),
            Symbol::LeftShift => write!(f, "<<"),
            Symbol::RightShift => write!(f, ">>"),
            Symbol::Ellipsis => write!(f, "..."),
            Symbol::ColonColon => write!(f, "::"),
        }
    }
}

impl std::fmt::Display for Keyword {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match self {
            Keyword::Return => write!(f, "return"),
            Keyword::Break => write!(f, "break"),
            Keyword::Continue => write!(f, "continue"),
            Keyword::If => write!(f, "if"),
            Keyword::Else => write!(f, "else"),
            Keyword::Elif => write!(f, "elif"),
            Keyword::For => write!(f, "for"),
            Keyword::While => write!(f, "while"),
            Keyword::Loop => write!(f, "loop"),
            Keyword::Match => write!(f, "match"),
            Keyword::Fn => write!(f, "fn"),
            Keyword::Struct => write!(f, "struct"),
            Keyword::Enum => write!(f, "enum"),
            Keyword::Const => write!(f, "const"),
            Keyword::Static => write!(f, "static"),
            Keyword::Type => write!(f, "type"),
            Keyword::As => write!(f, "as"),
            Keyword::In => write!(f, "in"),
            Keyword::Where => write!(f, "where"),
            Keyword::Async => write!(f, "async"),
            Keyword::Await => write!(f, "await"),
            Keyword::True => write!(f, "true"),
            Keyword::False => write!(f, "false"),
            Keyword::Null => write!(f, "null"),
            Keyword::New => write!(f, "new"),

            Keyword::Yield => write!(f, "yield"),
            Keyword::Import => write!(f, "import"),
            Keyword::Export => write!(f, "export"),
            Keyword::From => write!(f, "from"),
        }
    }
}

impl std::fmt::Display for Literal {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match self {
            Literal::Integer(n) => write!(f, "整数字面量: {}", n),
            Literal::Float(n) => write!(f, "浮点数字面量: {}", n),
            Literal::Char(c) => write!(f, "字符字面量: '{}'", c),
            Literal::String(s) => write!(f, "字符串字面量: \"{}\"", s),
            Literal::ByteString(bs) => write!(f, "字节字符串: {:?}", bs),
            Literal::Boolean(b) => write!(f, "布尔值: {}", b),
        }
    }
}
